import { isTextFieldEntryEdited, TextFieldEntry, Group } from '@bpmn-io/properties-panel';
import { useService } from 'bpmn-js-properties-panel';
import { is, getBusinessObject } from 'bpmn-js/lib/util/ModelUtil';

const LOW_PRIORITY = 500;
const ACTIVITI_PLATFORM_GROUPS = [UserAssignmentGroup];

export default class ActivitiPlatformPropertiesProvider {
  constructor(propertiesPanel, injector) {
    propertiesPanel.registerProvider(LOW_PRIORITY, this);
    this._injector = injector;
  }

  getGroups(element) {
    return groups => {
      groups = groups.concat(this._getGroups(element));
      return groups;
    };
  }

  _getGroups(element) {
    const groups = ACTIVITI_PLATFORM_GROUPS.map(createGroup => createGroup(element, this._injector));
    return groups.filter(group => group !== null);
  }

}

ActivitiPlatformPropertiesProvider.$inject = ['propertiesPanel', 'injector'];

function UserAssignmentGroup(element) {
  const group = {
    label: 'User assignment',
    id: 'ActivitiPlatform__UserAssignment',
    component: Group,
    entries: [...UserAssignmentProps({
      element
    })]
  };

  if (group.entries.length) {
    return group;
  }

  return null;
}

function UserAssignmentProps(props) {
  const {
    element
  } = props;

  if (!is(element, 'activiti:Assignable')) {
    return [];
  }

  return [{
    id: 'assignee',
    component: Assignee,
    isEdited: isTextFieldEntryEdited
  }, {
    id: 'candidateGroups',
    component: CandidateGroups,
    isEdited: isTextFieldEntryEdited
  }, {
    id: 'candidateUsers',
    component: CandidateUsers,
    isEdited: isTextFieldEntryEdited
  }];
}

function Assignee(props) {
  const {
    element
  } = props;
  const commandStack = useService('commandStack');
  const translate = useService('translate');
  const debounce = useService('debounceInput');
  const businessObject = getBusinessObject(element);

  const getValue = () => {
    return businessObject.get('activiti:assignee');
  };

  const setValue = value => {
    commandStack.execute('element.updateModdleProperties', {
      element,
      moddleElement: businessObject,
      properties: {
        'activiti:assignee': value
      }
    });
  };

  return TextFieldEntry({
    element,
    id: 'assignee',
    label: translate('Assignee'),
    getValue,
    setValue,
    debounce
  });
}

function CandidateUsers(props) {
  const {
    element
  } = props;
  const commandStack = useService('commandStack');
  const translate = useService('translate');
  const debounce = useService('debounceInput');
  const businessObject = getBusinessObject(element);

  const getValue = () => {
    return businessObject.get('activiti:candidateUsers');
  };

  const setValue = value => {
    commandStack.execute('element.updateModdleProperties', {
      element,
      moddleElement: businessObject,
      properties: {
        'activiti:candidateUsers': value
      }
    });
  };

  return TextFieldEntry({
    element,
    id: 'candidateUsers',
    label: translate('Candidate users'),
    getValue,
    setValue,
    debounce
  });
}

function CandidateGroups(props) {
  const {
    element
  } = props;
  const commandStack = useService('commandStack');
  const translate = useService('translate');
  const debounce = useService('debounceInput');
  const businessObject = getBusinessObject(element);

  const getValue = () => {
    return businessObject.get('activiti:candidateGroups');
  };

  const setValue = value => {
    commandStack.execute('element.updateModdleProperties', {
      element,
      moddleElement: businessObject,
      properties: {
        'activiti:candidateGroups': value
      }
    });
  };

  return TextFieldEntry({
    element,
    id: 'candidateGroups',
    label: translate('Candidate groups'),
    getValue,
    setValue,
    debounce
  });
}
